package main

import (
	"fmt"
	"reflect"
	"unsafe"
)

/*
  fmt的%p的值一般是数据实体的地址, slice和map比较特殊, 值是其结构体中arr的地址, 而不是结构体的地址;
  想拿到slice与map结构体的地址, 只能用unsafe.Pointer;
*/
func main() {
	SliceArrayType()
	IntPtr2ArrPtr()
	SliceStruct()
}

func SliceArrayType() {
	arr := []int{1, 3, 4}
	fmt.Printf("%p\n", arr)
	slice1 := arr[:]
	fmt.Printf("%p\n", slice1)
	slice2 := make([]int, 7)
	fmt.Println(reflect.TypeOf(slice2))  // []int
	fmt.Println(reflect.TypeOf(arr))     // []int
	fmt.Println(reflect.TypeOf(&slice2)) // *[]int
	fmt.Println(reflect.TypeOf(&arr))    // *[]int
}

// *int转*[8]byte (64位的int是8个字节)
func IntPtr2ArrPtr() {
	i := 0x1020
	var iptr *int
	iptr = &i
	var intP *[8]byte
	intP = (*[8]byte)(unsafe.Pointer(iptr))
	fmt.Println(intP[0], intP[1]) // 32 16
}

// 验证slice的数据结构
func SliceStruct() {
	// head = {address, 10, 10}
	// body = [1,2,3,4,5,6,7,8,9,10]
	var s = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	var address = (**[10]int)(unsafe.Pointer(&s))
	var length = (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + uintptr(8)))
	var cap = (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + uintptr(16)))
	fmt.Printf("%p\n", s)               // 0xc04207a0a0
	fmt.Printf("%p\n", *address)        // 0xc04207a0a0
	fmt.Printf("%p\n", address)         // 0xc04204e4c0
	fmt.Println(address, *length, *cap) // 0xc04204e4c0 10 10
	var body = **address
	for i := 0; i < len(body); i++ {
		fmt.Printf("%d ", body[i])
	}
}

// 利用pointer来转换str与byte
func str2bytes(s string) []byte {
	var strhead = *(*[2]int)(unsafe.Pointer(&s))
	var slicehead [3]int
	slicehead[0] = strhead[0]
	slicehead[1] = strhead[1]
	slicehead[2] = strhead[1]
	return *(*[]byte)(unsafe.Pointer(&slicehead))
}

func bytes2str(bs []byte) string {
	return *(*string)(unsafe.Pointer(&bs))
}
